/// 网络请求客户端
/// 
/// 基于Dio封装的HTTP请求客户端
/// 使用单例模式，确保全局只有一个实例
/// 自动添加token、请求日志、错误处理
/// 
/// 作者: Fluttert Team
/// 日期: 2024

import 'package:dio/dio.dart';
import '../constants/app_constants.dart';
import '../storage/storage_service.dart';
import '../../utils/logger_util.dart';

/// API客户端类
/// 
/// 提供GET、POST、PUT、DELETE等HTTP方法
/// 自动处理认证token和错误信息
class ApiClient {
  /// 单例实例
  static ApiClient? _instance;
  
  /// 获取单例实例
  /// 
  /// 使用懒加载模式，首次调用时创建实例
  static ApiClient get instance {
    _instance ??= ApiClient._();
    return _instance!;
  }

  /// Dio实例，用于发送HTTP请求
  late final Dio _dio;
  
  /// 存储服务实例，用于获取token等存储数据
  final StorageService _storage = StorageService.instance;

  /// 私有构造函数，实现单例模式
  ApiClient._() {
    _dio = Dio(
      BaseOptions(
        baseUrl: AppConstants.baseUrl,
        connectTimeout: AppConstants.connectTimeout,
        receiveTimeout: AppConstants.receiveTimeout,
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ),
    );

    // 添加请求拦截器
    _dio.interceptors.add(
      InterceptorsWrapper(
        // 请求拦截：自动添加token
        onRequest: (options, handler) async {
          // 从本地存储获取token并添加到请求头
          final token = await _storage.getString(AppConstants.tokenKey);
          if (token != null && token.isNotEmpty) {
            options.headers['Authorization'] = 'Bearer $token';
          }
          // 记录请求日志
          LoggerUtil.d('Request: ${options.method} ${options.uri}');
          return handler.next(options);
        },
        // 响应拦截：记录响应日志
        onResponse: (response, handler) {
          LoggerUtil.d('Response: ${response.statusCode} ${response.requestOptions.uri}');
          return handler.next(response);
        },
        // 错误拦截：记录错误日志
        onError: (error, handler) {
          LoggerUtil.e('Error: ${error.response?.statusCode} ${error.requestOptions.uri}');
          return handler.next(error);
        },
      ),
    );
  }

  /// GET请求
  /// 
  /// [path] 请求路径（相对于baseUrl）
  /// [queryParameters] 查询参数
  /// [options] 请求选项
  /// 返回响应数据
  Future<Response<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.get<T>(
        path,
        queryParameters: queryParameters,
        options: options,
      );
    } on DioException catch (e) {
      // 捕获Dio异常并转换为友好的错误信息
      throw Exception(_handleError(e));
    }
  }

  /// POST请求
  /// 
  /// [path] 请求路径
  /// [data] 请求体数据
  /// [queryParameters] 查询参数
  /// [options] 请求选项
  /// 返回响应数据
  Future<Response<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.post<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } on DioException catch (e) {
      throw Exception(_handleError(e));
    }
  }

  /// PUT请求
  /// 
  /// [path] 请求路径
  /// [data] 请求体数据
  /// [queryParameters] 查询参数
  /// [options] 请求选项
  /// 返回响应数据
  Future<Response<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.put<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } on DioException catch (e) {
      throw Exception(_handleError(e));
    }
  }

  /// DELETE请求
  /// 
  /// [path] 请求路径
  /// [data] 请求体数据（可选）
  /// [queryParameters] 查询参数
  /// [options] 请求选项
  /// 返回响应数据
  Future<Response<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.delete<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } on DioException catch (e) {
      throw Exception(_handleError(e));
    }
  }

  /// 处理Dio异常并转换为友好的错误信息
  /// 
  /// [error] Dio异常对象
  /// 返回错误描述字符串
  String _handleError(DioException error) {
    switch (error.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        return '请求超时，请检查网络连接';
      case DioExceptionType.badResponse:
        return '服务器错误: ${error.response?.statusCode}';
      case DioExceptionType.cancel:
        return '请求已取消';
      default:
        return '网络错误，请稍后重试';
    }
  }
}

